/* 
类
1. 抽象类， 可以包含抽象方法和抽象属性，抽象类不能被实例化，只能由子类来实例化，子类必须同时实现抽象方法和抽象属性；属性和方法可以指定为抽象，用 abstract 来修饰
2. 类的属性需要先声明后使用， 可以放到构造函数的参数中声明，此时可以少写点代码；
3. 类可以当做类型来使用，也可以当做值来使用  typeof AA 取其类型，等同于 AA
4. 


一、 修饰符,可以多个同时使用
1. public: 可以公开访问
2. protected: 只能自己（父类）和子类访问
3. private: 只能自己访问;
4. readonly: 只读，不可赋值;
二 、 super，用在子类中
1. 实例方法中的super指代的是父类的原型， 可以调用父类的实例方法；
2. 静态方法中的super指代的是父类，可以调用父类的静态方法；
三 、 静态属性和静态方法
1. 可以被子类所继承
四、 属性访问器，
> 可以借助用来访问私有属性, 如 private 和 protected 属性

 */


class Person {
    private name!: string
    private readonly age!: number
    protected constructor(name: string, age: number) {
        this.name = name
        this.age = age
    }
    static getName() {
        console.log('全人类');
    }
    eat() {
        console.log('吃饭');
    }

}

class Man extends Person {
    constructor(name: string, age: number) {
        super(name, age)
    }
    readonly gendar: any = 'man'
    static getName() {
        console.log(super.getName());
    }
    eat() { // 实例属性
        super.eat()
    }
    // 属性访问器
    private _niname: string = '' // 私有属性
    get niname() {
        return this._niname
    }
    set niname(newVal) {
        this._niname = newVal
    }

}

//---------------传入的参数必须是一个类------------------
// 以下两种写法都可以
function createClass(clazz: new () => Person) {
    // function createClass(clazz: { new(): Person }) {
}
//----------------------------------------------------

// class Woman extends Person {
//     static getName() {
//         console.log(super.getName());
//     }
//     say() {
//         super.say()
//     }

// }

// let p = new Person()
let p1 = new Man('张三', 23)
p1.niname = '小三子'
let p2 = new Man('李四', 35)
p2.niname = '小四儿'
// let p2 = new Woman()
console.log('----------', p1.eat === p2.eat);  // true 实例方法时共用的
console.log('----------', p1.niname);  // 小三子
console.log('----------', p2.niname);  // 小四儿
console.log('---niname-------', p1.niname === p2.niname);  // true 实例方法时共用的

// p.say()
export { }